home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume12 / psf2 / part06 < prev    next >
Encoding:
Text File  |  1990-05-19  |  41.8 KB  |  1,519 lines

  1. Newsgroups: comp.sources.misc
  2. From: tony@ajfcal.UUCP (Tony Field)
  3. subject: v12i109: psf2.0 source 6/6
  4. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5.  
  6. Posting-number: Volume 12, Issue 109
  7. Submitted-by: tony@ajfcal.UUCP (Tony Field)
  8. Archive-name: psf2/part06
  9.  
  10. psf2.0 source 6/6
  11. =================
  12. #! /bin/sh
  13. # This is a shell archive.  Remove anything before this line, then unpack
  14. # it by saving it into a file and typing "sh file".  To overwrite existing
  15. # files, type "sh file -c".  You can also feed this as standard input via
  16. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  17. # will see the following message at the end:
  18. #        "End of archive 6 (of 6)."
  19. # Contents:  psf.c
  20. # Wrapped by ajf@trifid on Tue May 15 01:10:54 1990
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'psf.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'psf.c'\"
  24. else
  25. echo shar: Extracting \"'psf.c'\" \(39736 characters\)
  26. sed "s/^X//" >'psf.c' <<'END_OF_FILE'
  27. X/* ta=4 */
  28. X/****************************************************************************
  29. X*                     p s f . c        v2.0                                    *
  30. X*                                                                            *
  31. X*    Postscript filter                                                        *
  32. X*                                                                            *
  33. X*    Print text files to postscript printer.  Allow 1-up, 2-up and 4-up        *
  34. X*    pages.  Provisions are made to allow font selection by imbedded            *
  35. X*    escape sequences - to allow printing of man pages.  The escape sequence    *
  36. X*    generated by "pnf" and "pmf" are compatible with psf.                    *
  37. X*                                                                            *
  38. X*    Copyright: 1989-Feb, Tony Field.       tony@ajfcal                        *
  39. X*                                                                            *
  40. X*    The orginal underline algorithm (/showunderline) was provided by        *
  41. X*    Anders Thulin        mcvax!helios!ath@uunet.uucp                        *
  42. X****************************************************************************/
  43. X
  44. X/*    NOTE:    tabstop=4    */
  45. X
  46. X/*    Note:    if you want psf to ignore any text that is already in postscript
  47. X            format, then possibly modify function "process_file()" to
  48. X            do the detection and copy the input file to stdout.
  49. X
  50. X            I haven't checked this out in detail, but it looks reasonable.
  51. X            Maybe a command line option should be used to enable/disable
  52. X            detection of postscript text (it is nice to be able to print
  53. X            out postscript code)?
  54. X*/
  55. X
  56. X/*    NOTES: re: -d option: double sided print.
  57. X
  58. X    Double sided print requires two scans over the data.  The first
  59. X    scan generates postscript output in normal (non-double sided) form.
  60. X    A second scan examines the postscript and re-orders the output
  61. X    to the printer.  The second pass is always done by the "psd" filter.
  62. X    
  63. X    Psf generates extra information to make it easy for psd to work.
  64. X    It simply constructs pointers to each of the %%Page: beginning
  65. X    in the print file.  (see function terminate_printer())  Psd
  66. X    uses the pointers to "skip about" the file while it does the
  67. X    actual page layout.
  68. X    
  69. X    If the target printer has two paper hoppers (i.e. #define HOPPER is
  70. X    defined and "nslots > 2") then psf creates a temp file and system("psd
  71. X    fname") is called to immediately generate the double sided output.
  72. X    The user does not have to manually invoke psd.
  73. X
  74. X    If HOPPER is not defined or nslots <= 1, psf simply creates an
  75. X    appropriate output file and the user must manually invoke psd to
  76. X    print the file.
  77. X
  78. X    Double sided print is forced into this routine. It would have been
  79. X    simple except for the fact that 2-up "book" format is supported.
  80. X    The excuse for this strategy is, of course, to minimize the amount
  81. X    of file processing overhead when double sided printing is done.
  82. X    
  83. X    If the double sided printing is for 8.5x5.5 inch paper printed
  84. X    two-up, then psf carefully forgets (in function set_frame())
  85. X    to put in page scale, rotation, and translation information.  
  86. X    The psd filter reads the page layout and carefully re-inserts 
  87. X    these when appropriate.  If 2-up "books" are made, each logical
  88. X    page becomes a separate page on the output temp file.
  89. X*/
  90. X
  91. X#include <stdio.h>
  92. X#include <math.h>
  93. X#include <time.h>
  94. X#include "patchlevel.h"
  95. X#include "psf.h"
  96. X
  97. X/*    BINDIR is used to locate double sided printer "psd".
  98. X    psd is called in function   output_book ()
  99. X    You may wish to remove the reference to "BINDIR" in output_book().
  100. X*/
  101. X
  102. X#ifndef BINDIR
  103. X#define BINDIR "\0"
  104. X#endif
  105. X
  106. X/*    set up the mechanism for underline display */
  107. X
  108. X#ifndef FONTINFO
  109. X#define SHOWU(fp,ps)    fprintf (fp, ") %d showuline\n", ps)
  110. X#else
  111. X#define SHOWU(fp,ps)    fputs (") showunderline\n", fp)
  112. X#endif
  113. X
  114. X#define MAX_PAGES    500        /* max pages in a book                        */
  115. X#define LONG_STR    1000    /* long buffer line                            */
  116. X
  117. X#define    min(x,y)        ((x) < (y) ? (x) : (y))
  118. X#define    max(x,y)        ((x) > (y) ? (x) : (y))
  119. X
  120. X/* default font with and height - assumes Courier fixed pitch                */
  121. X
  122. X#define NOMINAL_CWIDE    7.2        /* point width for Courier 12-point            */
  123. X#define NOMINAL_POINTS    12        /* standard 12-point for printing            */
  124. X
  125. X#define NORMAL        0x00        /* bitset for  print_attributes                */
  126. X#define ITALICS        0x01
  127. X#define BOLD        0x02
  128. X#define UNDERLINE    0x04        /* must be 0x04.  underline is not a font    */
  129. X
  130. X/* Paper physical dimensions.  Each paper size supported must be described.
  131. X    If the paper print areas specified are incorrect, you must modify them.
  132. X    The default paper sizes are coded into psf and are set for a NEC LC890
  133. X    printer.  These defaults are overridden in the "psfprint.def" printer
  134. X    definition file.
  135. X
  136. X    All text work must preserve the physical margins and scale the 
  137. X    drawing area to reflect the 1-up, 2-up or 4-up magnification.
  138. X
  139. X
  140. X    "paper_name" is the name used on the command line with the -g option
  141. X    to select the paper size:  eg   -g legal
  142. X    
  143. X    "paper_tray" is the command that is necessary to select the
  144. X    specified paper size. For example, if the "legal" sized paper is in
  145. X    the "alternate print tray", the postscript commands necessary to
  146. X    switch paper tray and to select the legal size must be specified in
  147. X    the "paper_tray" structure element. 
  148. X*/
  149. X
  150. Xtypedef struct                     /*    measurement in point                    */
  151. X{    char    paper_name[60];        /*    name of paper size (for command line)    */
  152. X    char    paper_tray[200];    /*    postscript operator to select this tray    */
  153. X    int        width;                /*    portrait point width of paper            */
  154. X    int        height;                /*    portrait point height of paper            */
  155. X    int        lx, ly, ux, uy;
  156. X    int        left_marg;            /*    margin widths (unprintable area)        */
  157. X    int        bot_marg;            /*            "                                */
  158. X    int        right_marg;            /*            "                                */
  159. X    int        top_marg;            /*            "                                */
  160. X    int        x_size;            /*    generated by psf.                        */
  161. X    int        y_size;            /*    size after correction for line count    */
  162. X    int        n_lines;            /*            "                                */
  163. X    int        n_chars;            /*            "                                */
  164. X} measure;
  165. X
  166. Xmeasure    *p;        /*    working set of parameters  (points to something below)     */
  167. X
  168. X                /*    standard paper sizes in portrait layout (NEC LC890)        */
  169. X                /*    These are defaults and are overridden in psfprint.def.    */
  170. X
  171. Xmeasure    page_types[30] =
  172. X{            {     "letter",
  173. X                "statusdict begin lettertray end",
  174. X                  612,   792,    18,    15,   593,   777
  175. X            },
  176. X            {     "legal",
  177. X                "statusdict begin legaltray end",
  178. X                  612,  1008,    18,    15,   593,   993
  179. X            },
  180. X            {    "a4",
  181. X                "statusdict begin a4tray end",
  182. X                  595,   842,    18,    15,   578,   827
  183. X            },
  184. X            {    "b5",
  185. X                "statusdict begin b5tray end",
  186. X                  516,   729,    18,    15,   497,   712
  187. X            },
  188. X            {    "",            /* end of paper list */
  189. X                "",
  190. X                 0, 0,  0,  0, 0, 0, 0, 0, 0, 0 
  191. X            }
  192. X};
  193. X
  194. Xchar    slots[4][100] = 
  195. X{            "statusdict begin 1 setpapertray end",
  196. X            "statusdict begin 2 setpapertray end",
  197. X            "",
  198. X            ""
  199. X} ;
  200. Xint        nslots = 2;
  201. X
  202. X
  203. X/* Current information about page.  Where are we, etc.  
  204. X*/
  205. X
  206. Xint        y_top_offset;            /*    offsets for each frame                    */
  207. Xint        x_left_offset;
  208. Xint        dx_home[4];                /*    page frame home (0,0) translations        */
  209. Xint        dy_home[4];
  210. X
  211. Xint        x,y;                    /* current x,y coordinate                    */
  212. Xdouble    scale_x, scale_y;        /* scale factors for 2-up, 4-up printing    */
  213. Xint        real_width;
  214. X
  215. Xlong    *pg_loc;                /* double side print byte ptr to %%Page:    */
  216. Xint        npg_loc;                /* number of elements in pg_loc[]            */
  217. X
  218. Xint        book             = 0;    /* book format: double sided                */
  219. Xint        bookwork        = 0;    /* book format, 2-up print                    */
  220. Xint        lines_on_page     = 60;    /* user print lines on page                    */
  221. Xint        lines_total     = 0;    /* total number of lines for scale purposes    */
  222. Xint        chars_on_line     = 80;    /* default number of chars on line            */
  223. Xint        landscape         = 0;    /* 1 = landscape, 0 = portrait layout        */
  224. Xint        header            = 0;    /* 1 = print header at top of each page        */
  225. Xint        cross              = 0;    /* 1 = print cross on 4-up pages            */
  226. Xint        line_number        = 0;    /* current logical line number on page        */
  227. Xint        tab_size           = 8;    /* space translation for tabs.                */
  228. Xint        font_number     = 0;    /* one of the valid fonts in the printer    */
  229. Xint        point_size        = 12;    /* can be changed with the -p option        */
  230. Xint        x_user_offset     = 0;    /* offsets specified buy user                */
  231. Xint        y_user_offset     = 0;    /* points from physical page edge.            */
  232. Xint        set_paper_tray     = 0;    /* user has set paper tray selection        */
  233. Xint        set_line_count     = 0;    /*                print line count on page    */
  234. Xint        set_total_count    = 0;    /*                total line count on page    */
  235. Xint        set_point_size     = 0;    /*                point size                    */
  236. Xint        set_char_count     = 0;    /*                characters on a line        */
  237. Xint        set_paper_bin    = 0;    /*                paper bin (not page size)    */
  238. Xchar    header_text[100];        /*                header line text            */
  239. X
  240. Xint        print_attribute = 0;    /* such as BOLD, UNDERLINE, ITALICS            */
  241. Xint        default_font_number;    /* set with -f option, or 0                    */
  242. Xint        default_point_size;        /* assumes value due to -p option            */
  243. Xint        y_coord            = 0;    /* current logical page y-coordinate, points*/
  244. Xint        x_coord            = 0;    /* current logical page x-coordinate, points*/
  245. Xint        page_number;            /* current page number for this file        */
  246. Xint        physical_page     = 0;    /* postscript physical page for multi-up    */
  247. X
  248. X
  249. Xchar    fname[100];
  250. Xchar    now[50];                /* time of day for page headers             */
  251. X
  252. X
  253. X/*    to select a font, use 4 * font_number + print_attribute as index.
  254. X    e.g.   If font_number = 1    for Helvetica,
  255. X      and print_attribute = 0x02 for BOLD
  256. X
  257. X    then the actual font selected is    fonts[4 * 1 + 2]
  258. X                                        = Helvetica-Bold
  259. X
  260. X    The various print attributes can be OR'ed together:
  261. X            fonts [4 * 1 + ITALICS | BOLD] 
  262. X
  263. X    The following are default fonts - and are overridden in psfprint.def.
  264. X*/
  265. X      
  266. X#define NFONTS      40            /*     4 variations * 9 font families  */
  267. Xchar *fonts[NFONTS] =
  268. X{
  269. X    "Courier",                    "Courier-Oblique",            "Courier-Bold",             "Courier-BoldOblique",
  270. X    "Helvetica",                 "Helvetica-Oblique",         "Helvetica-Bold",            "Helvetica-BoldOblique",
  271. X    "Times-Roman",                 "Times-Italic",             "Times-Bold",                 "Times-BoldItalic",
  272. X    "AvantGarde-Book",          "AvantGarde-BookOblique",   "AvantGarde-Demi",          "AvantGarde-DemiOblique",
  273. X    "Bookman-Light",            "Bookman-LightItalic",      "Bookman-Demi",             "Bookman-DemiItalic",
  274. X    "NewCenturySchlbk-Roman",   "NewCenturySchlbk-Italic",  "NewCenturySchlbk-Bold",    "NewCenturySchlbk-BoldItalic",
  275. X    "Palatino-Roman",           "Palatino-Italic",          "Palatino-Bold",            "Palatino-BoldItalic",
  276. X    "Helvetica-Narrow",         "Helvetica-Narrow-Oblique", "Helvetica-Narrow-Bold",    "Helvetica-Narrow-BoldOblique",
  277. X    "Garamond-Light",            "Garamond-LightItalic",        "Garamond-Bold",            "Garamond-BoldItalic",
  278. X    "ZapfChancery-MediumItalic","ZapfChancery-MediumItalic","ZapfChancery-MediumItalic","ZapfChancery-MediumItalic"
  279. X} ;
  280. X
  281. Xint    fonts_used[NFONTS];
  282. Xint    fonts_have[NFONTS];
  283. X
  284. Xint    max_frame    = 1;        /* max number of frames in use */
  285. Xint    frame        = -1;        /* current frame in use */
  286. X
  287. XFILE    *input_fp, *output_fp;
  288. X
  289. X/*    input line and input line pointer */
  290. Xunsigned char    *c;
  291. Xunsigned char    line[LONG_STR + 1];
  292. X
  293. Xchar    *pgmname;
  294. X
  295. Xchar    *malloc();
  296. X
  297. Xmain (argc, argv)
  298. Xint        argc;
  299. Xchar    *argv[];
  300. X{    int        c, i, j;
  301. X    extern char *optarg;
  302. X    extern int    optind;
  303. X    FILE    *pdef;
  304. X    
  305. X    /*    see if there is a psfprint.def printer definition file.  If so,
  306. X        use those parameters, rather than the hard-coded defaults.
  307. X    */
  308. X
  309. X    if ((pdef = fopen (PDEF, "r")) != NULL)
  310. X    {    nslots = 0;
  311. X        fgets (line, 100, pdef);
  312. X        for (i = 0;  i < 28;  i++)
  313. X        {    if (fgets (page_types[i].paper_name, 59, pdef) == NULL)
  314. X                break;
  315. X            trim (page_types[i].paper_name);
  316. X            if (strncmp (page_types[i].paper_name, "*fonts", 6) == 0)
  317. X            {
  318. X                for (j = 0;  j < NFONTS;  j++)
  319. X                    fonts_have[j] = 0;
  320. X                page_types[i].paper_name[0] = '\0';
  321. X                while (fgets (line, 90, pdef) != NULL)
  322. X                {    trim (line);
  323. X                    if (*line == '*')
  324. X                        break;
  325. X                    for (j = 0;  j < NFONTS;  j++)
  326. X                    {    if (comp (fonts[j], line) == 0)
  327. X                        {    fonts_have[j] = 1;
  328. X                            break;
  329. X                        }
  330. X                    }
  331. X                }
  332. X                if (strncmp (line, "*slots", 6) == 0)
  333. X                {    while (fgets (line, 90, pdef) != NULL)
  334. X                    {    trim (line);
  335. X                        if (strncmp (line, "*eof", 4) == 0)
  336. X                            break;
  337. X                        if (*line)
  338. X                        {
  339. X                            strcpy (slots[nslots], line);
  340. X                            if (++nslots > 3)
  341. X                                break;
  342. X                        }
  343. X                    }
  344. X                }
  345. X                break;        /* end of file */
  346. X            }
  347. X            if (fgets (page_types[i].paper_tray, 199, pdef) == NULL)
  348. X                bad_file();
  349. X            trim (page_types[i].paper_tray);
  350. X            if (fgets (line, 100, pdef) == NULL)
  351. X                bad_file();
  352. X            trim (line);
  353. X            sscanf (line, "%d%d%d%d%d%d",
  354. X                &page_types[i].width,
  355. X                &page_types[i].height,
  356. X                &page_types[i].lx,
  357. X                &page_types[i].ly,
  358. X                &page_types[i].ux,
  359. X                &page_types[i].uy);
  360. X
  361. X        }
  362. X        page_types[i].paper_name[0] = '\0';
  363. X        fclose (pdef);
  364. X    }
  365. X    else
  366. X    {    for (i = 0;  i < NFONTS;  i++)
  367. X            fonts_have[i] = 1;
  368. X        fonts_have[8] = 0;
  369. X    }
  370. X
  371. X    for (i = 0;  page_types[i].paper_name[0];  i++)
  372. X    {    page_types[i].left_marg  = page_types[i].lx;
  373. X        page_types[i].bot_marg   = page_types[i].ly;
  374. X        page_types[i].top_marg   = (page_types[i].height - 1) - page_types[i].uy;
  375. X        page_types[i].right_marg = (page_types[i].width  - 1) - page_types[i].ux;
  376. X
  377. X        page_types[i].x_size = page_types[i].ux - page_types[i].lx + 1;
  378. X        page_types[i].y_size = page_types[i].uy - page_types[i].ly + 1;
  379. X    }
  380. X        
  381. X    pgmname = argv[0];
  382. X    p = &page_types[0];            /* default to letter size paper    */
  383. X    *header_text = '\0';
  384. X    scale_x = 1.0;
  385. X    scale_y = 1.0;
  386. X    if (strcmp (argv[1], "-") == 0  || strcmp (argv[1], "--") == 0)
  387. X        usage();
  388. X    while ((c = getopt(argc, argv, "124xhnwdi:m:b:c:g:H:l:L:f:t:p:-?")) != -1)
  389. X    {    switch (c)
  390. X        {
  391. X        case '1':
  392. X            max_frame = 1;
  393. X            scale_x = 1.0;
  394. X            scale_y = 1.0;
  395. X            break;
  396. X            
  397. X        case '2':
  398. X            landscape = 1;
  399. X            max_frame = 2;
  400. X            scale_x = 0.647;
  401. X            scale_y = 0.772;
  402. X            break;
  403. X        
  404. X        case '4':
  405. X            max_frame = 4;
  406. X            scale_x = 0.5;
  407. X            scale_y = 0.5;
  408. X            break;
  409. X            
  410. X        case 'b':
  411. X            if ((set_paper_bin = atoi (optarg)) > nslots)
  412. X            {    if (nslots = 0)
  413. X                    fprintf (stderr, "%s: no alternate bins permitted for this printer\n", nslots);
  414. X                else
  415. X                    fprintf (stderr, "%s: paper bin greater than %d\n", pgmname, nslots);
  416. X                exit (1);
  417. X            }
  418. X            break;
  419. X
  420. X        case 'c':
  421. X            chars_on_line = atoi (optarg);
  422. X            set_char_count = 1;
  423. X            break;
  424. X
  425. X        case 'd':
  426. X            book = 1;
  427. X            break;
  428. X                    
  429. X        case 'f':
  430. X            if (*optarg > '9')
  431. X            {    for (i = 0;  i < NFONTS;  i += 4)
  432. X                {    if (compare (optarg, fonts[i]) == 0)
  433. X                    {    font_number =  i / 4;
  434. X                        break;
  435. X                    }
  436. X                }
  437. X                if (i >= NFONTS)
  438. X                    font_number = 0;
  439. X            }
  440. X            else
  441. X            {
  442. X                font_number = atoi (optarg);
  443. X                if (font_number > (NFONTS / 4))
  444. X                    font_number = 0;
  445. X            }
  446. X            break;
  447. X
  448. X        case 'g':
  449. X            p = NULL;
  450. X            for (i = 0;  page_types[i].paper_name[0];  i++)
  451. X            {    if (compare (optarg, page_types[i].paper_name) == 0)
  452. X                {    p = &page_types[i];
  453. X                    break;
  454. X                }
  455. X            }
  456. X            if (p == NULL)
  457. X                usage ();
  458. X            set_paper_tray = 1;
  459. X            break;
  460. X
  461. X        case 'l':
  462. X            lines_on_page = atoi (optarg);
  463. X            set_line_count = 1;
  464. X            break;
  465. X
  466. X        case 'L':
  467. X            lines_total = atoi (optarg);
  468. X            set_total_count = 1;
  469. X            break;
  470. X            
  471. X        case 'h':
  472. X            header = 1;
  473. X            break;
  474. X            
  475. X        case 'H':
  476. X            header = 2;
  477. X            strcpy (header_text, optarg);
  478. X            break;
  479. X            
  480. X        case 'i':
  481. X            x_user_offset = atoi (optarg);
  482. X            break;
  483. X            
  484. X        case 'm':
  485. X            y_user_offset = atoi (optarg);
  486. X            break;
  487. X            
  488. X        case 'n':
  489. X            landscape = 0;
  490. X            break;
  491. X
  492. X        case 'p':
  493. X            point_size = atoi (optarg);
  494. X            set_point_size = 1;
  495. X            break;
  496. X            
  497. X        case 't':
  498. X            tab_size = atoi (optarg);
  499. X            break;
  500. X        
  501. X        case 'w':
  502. X            landscape = 1;
  503. X            break;
  504. X            
  505. X        case 'x':
  506. X            cross = 1;
  507. X            break;
  508. X
  509. X        default:    usage ();
  510. X            break;
  511. X        }
  512. X    }
  513. X
  514. X    if (font_number * 4 > NFONTS)
  515. X    {    fprintf (stderr,"Font number invalid....\n");
  516. X        usage ();
  517. X    }
  518. X    
  519. X    if (header)
  520. X        lines_on_page += 2;
  521. X
  522. X#ifdef HOPPER
  523. X    if (book  &&  nslots > 1)
  524. X    {
  525. X        if ((output_fp = fopen ("1psbook2.d34", "w")) == NULL)
  526. X        {    fprintf (stderr, "%s: cannot create work file\n", pgmname);
  527. X            exit (1);
  528. X        }
  529. X    }
  530. X    else    
  531. X#endif
  532. X        output_fp = stdout;
  533. X
  534. X    if (book)
  535. X    {    if ((pg_loc = (long *) malloc (sizeof (long) * MAX_PAGES)) == NULL)
  536. X        {    fprintf (stderr, "%s: cannot allocate enough memory\n", pgmname);
  537. X            exit (1);
  538. X        }
  539. X        npg_loc = 0;
  540. X    }
  541. X
  542. X    for (i = 0;  i < NFONTS;  i++)
  543. X        fonts_used[i] = 0;
  544. X
  545. X    page_number = -1;
  546. X    line_number = 32000;
  547. X    default_point_size = point_size;
  548. X    default_font_number = font_number;
  549. X    bookwork = book  &&  landscape  &&  (max_frame == 2);
  550. X    *fname = 0;    
  551. X
  552. X    get_time (now);        
  553. X    scale_factors ();
  554. X    prologue (output_fp);
  555. X    if (optind >=  argc)
  556. X    {    if (header == 1)
  557. X            header = 0;
  558. X        start_file ();
  559. X        input_fp = stdin;
  560. X        process_file ();
  561. X        terminate_file ();
  562. X    }
  563. X    else for ( ;  optind < argc;  optind++)
  564. X    {    i = strlen (argv[optind]);
  565. X        if (i > 38)
  566. X            i -= 38;
  567. X        else
  568. X            i = 0;
  569. X        strcpy (fname, argv[optind] + i);
  570. X        if ((input_fp = fopen (argv[optind], "r")) == NULL)
  571. X        {    fprintf (stderr, "Unknown file: %s\n", argv[optind]);
  572. X            continue;
  573. X        }
  574. X        start_file ();
  575. X        process_file ();
  576. X        terminate_file ();
  577. X        fclose (input_fp);
  578. X    }
  579. X    terminate_printer ();
  580. X
  581. X    if (book)
  582. X        output_book ();
  583. X
  584. X    exit (0);
  585. X}
  586. X
  587. X/****************************************************************************
  588. X*    scale_factors ()                                                        *
  589. X*    Compute the x and y scale factors.  If the print is for landscape,        *
  590. X*    adjust the paper size matrix (p->...) to reflect landscape rather        *
  591. X*    than portrait.                                                            *
  592. X****************************************************************************/
  593. X
  594. X/*    scale factors are calculated from:
  595. X
  596. X    unprintable size  +  scale factor  *  print size  =  total paper size
  597. X    
  598. X                    total paper size - unprintable size
  599. X    scale factor = --------------------------------------
  600. X                            print size
  601. X*/
  602. X
  603. Xscale_factors ()
  604. X{    int    wide;                /*    width needed for char count            */
  605. X    int    high;                /*    points needed for line count        */
  606. X    int    i;
  607. X    double    char_width, scale;
  608. X
  609. X    /*    determine default number of characters and lines based upon
  610. X        Courier 12 point, 10 pitch font, portrait layout
  611. X    */
  612. X
  613. X    char_width = NOMINAL_CWIDE;    /* in points                        */
  614. X    real_width = p->width;        /* for initial axis translate only    */
  615. X
  616. X    p->n_chars = ceil ((double) p->x_size / NOMINAL_CWIDE);
  617. X    p->n_lines = p->y_size / NOMINAL_POINTS;
  618. X
  619. X    /*    set line count relative to portrait measure */
  620. X
  621. X    if (set_total_count == 0)
  622. X        lines_total = p->n_lines;
  623. X
  624. X    if (set_line_count == 0)
  625. X        lines_on_page = p->n_lines;
  626. X
  627. X    if (lines_total < lines_on_page)
  628. X    {    if (set_total_count)
  629. X            lines_on_page = lines_total;
  630. X        else
  631. X            lines_total = lines_on_page;
  632. X    }
  633. X
  634. X    /*    if landscape, then switch the height and width dimensions      */
  635. X    
  636. X    if (landscape)
  637. X    {
  638. X        i = p->height;      p->height    = p->width;        p->width      = i;
  639. X        i = p->left_marg;   p->left_marg = p->bot_marg;     p->bot_marg   = i;
  640. X        i = p->top_marg;    p->top_marg  = p->right_marg;   p->right_marg = i;
  641. X        i = p->lx;            p->lx        = p->ly;            p->ly          = i;
  642. X        i = p->ux;            p->ux        = p->uy;            p->uy          = i;
  643. X        i = p->x_size;        p->x_size    = p->y_size;        p->y_size      = i;
  644. X        
  645. X        if (max_frame == 1)
  646. X        {    scale = (double) p->y_size / (double) p->x_size;
  647. X            p->n_chars = ceil ((double) p->n_chars * scale * scale);
  648. X        }
  649. X    }
  650. X    if (set_char_count == 0)
  651. X        chars_on_line = p->n_chars;
  652. X
  653. X    if (set_point_size)
  654. X    {    scale = (double) point_size / (double) NOMINAL_POINTS;
  655. X        lines_total = p->y_size / point_size;
  656. X        if (set_char_count == 0)
  657. X        {    chars_on_line /= scale;
  658. X            char_width    *= scale;
  659. X        }
  660. X    }
  661. X    else if (set_line_count  ||  set_total_count)
  662. X    {
  663. X        if (set_char_count == 0)
  664. X        {    scale = (double) lines_total / (double) p->n_lines;
  665. X            chars_on_line = ceil ((double) chars_on_line * scale);
  666. X        }
  667. X    }
  668. X
  669. X    /*    Ideally, we wish to use a decender value of 0.5 line.
  670. X        This is yieds a scale factor of 1.0 for Courier in default
  671. X        portrait mode.  Hopefully, this is not a problem with
  672. X        other fonts.
  673. X    */
  674. X    high = ceil ((double) point_size * ((double) lines_total + 0.51));
  675. X    wide = ceil (chars_on_line * char_width);
  676. X
  677. X    x_user_offset = max (0, x_user_offset - p->left_marg);
  678. X    y_user_offset = max (0, y_user_offset - p->top_marg );
  679. X
  680. X    switch (max_frame)
  681. X    {
  682. X    case 1:
  683. X        scale_x = (double) (p->x_size) / (double) wide;
  684. X        scale_y = (double) (p->y_size) / (double) high;
  685. X        x_left_offset  = (int) ceil ((double) (p->left_marg + x_user_offset) / scale_x);
  686. X        y_top_offset   = (int) ceil ((double) (p->top_marg  + y_user_offset) / scale_y);
  687. X        dx_home[0] = 0;
  688. X        dy_home[0] = 0;
  689. X        p->height = ceil ((double) p->height / scale_y);
  690. X        p->width  = ceil ((double) p->width / scale_x);
  691. X        p->bot_marg = ceil ((double) p->bot_marg / scale_y);
  692. X        break;
  693. X    
  694. X    case 2:
  695. X        scale_x = (double) (p->width - 2 * p->left_marg - 2 * p->right_marg)
  696. X                / (double) (2 * wide);
  697. X        scale_y = (double) (p->y_size) / (double) high;
  698. X
  699. X        /*    point offsets for margins account for physical "forbidden" area */
  700. X
  701. X        x_left_offset  = (int) ceil ((double) p->left_marg / scale_x);
  702. X        y_top_offset   = (int) ceil ((double) p->top_marg / scale_y);
  703. X        
  704. X        /*    page origin translation vectors    */
  705. X        
  706. X        p->height = ceil ((double) p->height / scale_y);
  707. X        p->width  = ceil ((double) p->width  / (scale_x * 2.0));
  708. X        p->bot_marg = ceil ((double) p->bot_marg / scale_y);
  709. X        dx_home[0] = 0;
  710. X        dy_home[0] = 0;
  711. X        dx_home[1] = p->width;
  712. X        dy_home[1] = 0;
  713. X        break;
  714. X    
  715. X    case 4:
  716. X        scale_x = (double) (p->width - 2 * p->left_marg - 2 * p->right_marg)
  717. X                / (double) (2 * wide);
  718. X        scale_y = (double) (p->height - 2 * p->top_marg - 2 * p->bot_marg)
  719. X                / (double) (2 * high);
  720. X
  721. X        /*    point offsets for margins account for physical "forbidden" area */
  722. X
  723. X        x_left_offset = (int) ceil ((double) p->left_marg / scale_x);
  724. X        y_top_offset  = (int) ceil ((double) p->top_marg / scale_y);
  725. X        
  726. X        /*    page origin tranlsation vectors    */
  727. X        
  728. X        p->height = ceil ((double) p->height / (scale_y * 2.0));
  729. X        p->width  = ceil ((double) p->width  / (scale_x * 2.0));
  730. X        p->bot_marg = ceil ((double) p->bot_marg / scale_y);
  731. X        dx_home[0] = 0;
  732. X        dy_home[0] = p->height;
  733. X        dx_home[1] = 0;
  734. X        dy_home[1] = -p->height;
  735. X        dx_home[2] = p->width;
  736. X        dy_home[2] = p->height;
  737. X        dx_home[3] = 0;
  738. X        dy_home[3] = -p->height;
  739. X        break;
  740. X    
  741. X    default: ;
  742. X    }
  743. X
  744. X    if (max_frame > 1)
  745. X    {    x_left_offset += x_user_offset;
  746. X        y_top_offset  += y_user_offset;
  747. X    }
  748. X    
  749. X#ifdef DEBUG
  750. X    printf ("%%!PS-Adobe-\n");
  751. X    printf ("%% lines =%d/%d/%d  chars = %d/%d\n", lines_total, set_line_count,set_total_count, chars_on_line, set_char_count);
  752. X    printf ("%% height     = %d / %d\n", p->height, high);
  753. X    printf ("%% width      = %d / %d\n", p->width, wide);
  754. X    printf ("%% (lx,ly)    = (%d,%d)\n", p->lx, p->ly);
  755. X    printf ("%% (ux,uy)    = (%d,%d)\n", p->ux, p->uy);
  756. X    printf ("%% left_marg  = %d\n", p->left_marg);
  757. X    printf ("%% right_marg = %d\n", p->right_marg);
  758. X    printf ("%% top_marg   = %d\n", p->top_marg);
  759. X    printf ("%% bot_marg   = %d\n", p->bot_marg);
  760. X    printf ("%% y_size     = %d\n", p->y_size);
  761. X    printf ("%% x_size     = %d\n", p->x_size);
  762. X    printf ("%% scale_x = %f   scale_y = %f\n", scale_x, scale_y);
  763. X    printf ("%% offset (lx,ty) = (%d,%d)\n", x_left_offset,  y_top_offset);
  764. X    printf ("%% home       = %d %d %d %d\n",dy_home[0], dy_home[1], dy_home[2],dy_home[3]);
  765. X#endif
  766. X}
  767. X
  768. X
  769. X/****************************************************************************
  770. X*    prologue ()                                                                *
  771. X*    generate the require postscript-conformant prologue                        *
  772. X****************************************************************************/
  773. X
  774. Xprologue ()
  775. X{    char    *getlogin();
  776. X    int        i;
  777. X
  778. X    if (book)
  779. X        fprintf (output_fp, "%%Book file: psf-to-psd\n");
  780. X    else
  781. X        fprintf (output_fp, "%%!PS-Adobe-\n");
  782. X    fprintf (output_fp, "%%%%Creator: %s\n", getlogin());
  783. X    fprintf (output_fp, "%%%%CreationDate: %s\n", now);
  784. X    fprintf (output_fp, "%%%%DocumentFonts: (atend)\n");
  785. X    fprintf (output_fp, "%%%%Pages: (atend)\n");
  786. X    fprintf (output_fp, "%%%%EndComments\n");
  787. X    
  788. X#ifndef FONTINFO
  789. X    /*     The red book (pg 93) indicates that the FontInfo dictionary
  790. X        "MAY" contain the /UnderlinePosition and /UnderlineThickness
  791. X        This is the case for all Adobe fonts.  External non-Adobe fonts may
  792. X        not have these values.
  793. X        
  794. X        usage:         (text to underline) <pointsize> showuline
  795. X        where:        <pointsize> is current text point size.
  796. X
  797. X        eg:            (text to underline) 12 showuline
  798. X    */
  799. X    fprintf (output_fp, "%s%s%s%s%s%s%s%s%s%s",
  800. X            "/showuline {\n",
  801. X            "    /CurPointSize exch def\n",
  802. X            "    dup stringwidth pop\n",
  803. X            "    gsave\n",
  804. X            "    currentfont /FontInfo get dup\n",
  805. X            "    /UnderlinePosition get CurPointSize mul 1000 div 0 exch rmoveto exch 0 rlineto\n",
  806. X            "    /UnderlineThickness get CurPointSize mul 1000 div setlinewidth stroke\n",
  807. X            "    grestore\n",
  808. X            "    show\n",
  809. X            "} def\n");
  810. X
  811. X#else
  812. X    /*    showunderline: without FontInfo:  underline is 2 points below base 
  813. X        compliments of Anders Thulin
  814. X                        mcvax!helios!ath@uunet.uucp (Anders Thulin)
  815. X
  816. X        usage:        (text to underline) showunderline
  817. X    */
  818. X    fprintf (output_fp, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
  819. X            "/showunderline {\n",
  820. X            "  /str exch def\n",
  821. X            "  /dy     0 def\n",
  822. X            "  currentpoint\n",
  823. X            "    str show\n",
  824. X            "  moveto\n",
  825. X            "  /dy -2 def\n",
  826. X            "  currentpoint\n",
  827. X            "  dy add\n",
  828. X            "  moveto\n",
  829. X            "  str stringwidth\n",
  830. X            "  rlineto \n",
  831. X            "  currentpoint\n",
  832. X            "    stroke\n",
  833. X            "  moveto\n",
  834. X            "  currentpoint\n",
  835. X            "  dy sub\n",
  836. X            "  moveto\n",
  837. X            "} def\n");
  838. X#endif
  839. X
  840. X    fprintf (output_fp, "%%%%EndProlog\n");
  841. X
  842. X    if (set_paper_tray)
  843. X        fprintf (output_fp, "%s\n", p->paper_tray);
  844. X
  845. X    if (set_paper_bin)
  846. X        fprintf (output_fp, "%s\n", slots[set_paper_bin - 1]);
  847. X}
  848. X
  849. X/****************************************************************************
  850. X*    new_page ()                                                                *
  851. X*    Generate a new page.  Send out required rotation,scale information        *
  852. X*    This is the "prologue" to a page (not the end of the previous)            *
  853. X****************************************************************************/
  854. X
  855. Xnew_page ()
  856. X{
  857. X}
  858. X
  859. X
  860. X/****************************************************************************
  861. X*    showpage ()                                                                *
  862. X*    Generate a real "showpage" if we have really finished generating a        *
  863. X*    physical page.  If we are processing 2 or 4 up, then generate             *
  864. X*    coordinate "translates" if we really haven't finished all possible        *
  865. X*    page frames of the page.                                                *
  866. X****************************************************************************/
  867. X
  868. Xshowpage (end_of_file)
  869. Xint end_of_file;
  870. X{
  871. X    line_number = 0;
  872. X
  873. X    if (++frame >= max_frame  ||  end_of_file)
  874. X    {    if (bookwork == 0)                    /* psd will re-insert this */
  875. X            fprintf (output_fp, "showpage pg restore\n");
  876. X        frame = 0;
  877. X    }
  878. X    if (!end_of_file)
  879. X        set_frame ();
  880. X}
  881. X
  882. X/****************************************************************************
  883. X*    set_frame ()                                                            *
  884. X*    Select the next logical frame in two-up or four-up mode.  If it is        *
  885. X*    the first frame of a physical page, the generate the %%Page                *
  886. X****************************************************************************/
  887. X
  888. Xset_frame ()
  889. X{
  890. X    if (frame == 0  ||  bookwork)
  891. X    {
  892. X        if (book)        /*    mark byte position of %%Page: for psd  */
  893. X        {    pg_loc[npg_loc++] = ftell (output_fp);
  894. X        }
  895. X        fprintf (output_fp, "%%%%Page: ? %d\n", ++physical_page);
  896. X        if (bookwork == 0)                    /* psd will re-insert these */
  897. X        {    fprintf (output_fp, "/pg save def\n");
  898. X            if (landscape)
  899. X                fprintf (output_fp, "90 rotate 0 %d translate\n", -real_width);
  900. X            fprintf (output_fp, "%.5f %.5f scale\n", scale_x, scale_y);
  901. X        }
  902. X        findfont();
  903. X    }
  904. X    set_y_coord ();
  905. X
  906. X    if (max_frame > 1  &&  bookwork == 0)
  907. X        fprintf (output_fp, "%d %d translate\n", dx_home[frame], dy_home[frame]);
  908. X
  909. X    if (frame == 0  &&  cross)
  910. X        draw_cross();
  911. X
  912. X}
  913. X
  914. X
  915. X/****************************************************************************
  916. X*    set_y_coord                                                                *
  917. X*    position next line to the top of a logical page.                        *
  918. X*****************************************************************************/
  919. X
  920. Xset_y_coord ()
  921. X{
  922. X    y_coord = p->height - y_top_offset - point_size;
  923. X}
  924. X
  925. X/****************************************************************************
  926. X*    put_top                                                                    *
  927. X*    put a header line at the top of the page                                *
  928. X*****************************************************************************/
  929. X
  930. Xput_top ()
  931. X{
  932. X    int    save_attr, save_point;
  933. X    
  934. X    save_attr = print_attribute;
  935. X    save_point = point_size;
  936. X    print_attribute = BOLD;
  937. X    point_size = 12;
  938. X    
  939. X    findfont();
  940. X    moveto (0, y_coord, 1);
  941. X    if (header == 1)
  942. X        fprintf (output_fp, "(%-40s %3d     %s)show\n", fname, page_number + 1, now);
  943. X    else
  944. X        fprintf (output_fp, "(%-40s %3d     %s)show\n", header_text, page_number + 1, now);
  945. X    y_coord -= point_size * 2;
  946. X    x_coord = 0;
  947. X    print_attribute = save_attr;
  948. X    point_size = save_point;
  949. X    findfont();
  950. X}
  951. X
  952. X/****************************************************************************
  953. X*    process_file()                                                            *
  954. X*    Read the file, look for escape sequences, put text in postscript form    *
  955. X****************************************************************************/
  956. X
  957. Xprocess_file ()
  958. X{
  959. X    int        char_type, char_count, i, set_page, esc_type;
  960. X    char    *strchr ();
  961. X    int        previous_attribute;
  962. X    int        lcount = 0;
  963. X    
  964. X    set_page = 0;
  965. X    while (fgets (line, LONG_STR, input_fp) != NULL)
  966. X    {
  967. X        if (lcount++ == 0)
  968. X        {    if ((i = tscan (line, "ta=")) >= 0)
  969. X            {    tab_size = atoi (line + i + 3);
  970. X            }
  971. X            /*    we could also test here to see if the file is already
  972. X                in postscript format and simply copy out the file
  973. X                to stdout - however, we couldn't print postscript source.
  974. X                By choice, detection of postscript is left to "psdetect"
  975. X                in the back-end spooler.
  976. X               
  977. X                e.g.   print postscript source with:
  978. X                
  979. X                        psf thisfile.ps | lp
  980. X                
  981. X                will work even if psf is working in the print spooler.
  982. X            */
  983. X        }
  984. X        if ((c = (unsigned char *) strchr (line, '\f')) != NULL)
  985. X        {
  986. X            if (c == line)
  987. X            {    line_number = 32000;
  988. X                c = line + 1;
  989. X            }
  990. X            else
  991. X            {    *c = 0;
  992. X                set_page = 1;
  993. X                c = line;
  994. X            }
  995. X        }
  996. X        else
  997. X            c = line;
  998. X
  999. X        if (line_number >= lines_on_page * 10)
  1000. X        {    page_number++;
  1001. X            showpage (0);
  1002. X            line_number = 10;
  1003. X            if (header)
  1004. X            {
  1005. X                put_top();
  1006. X                line_number += 20;
  1007. X            }
  1008. X        }
  1009. X        else
  1010. X            line_number += 10;
  1011. X
  1012. X        char_type = char_count = 0;
  1013. X
  1014. X        /*    for empty lines, don't generate a real moveto - but to call
  1015. X            to ensure that check for page overflow is done.
  1016. X        */
  1017. X        if (*c == '\n')
  1018. X            moveto (x_coord, y_coord, 0);        /*    don't gen moveto    */
  1019. X        else
  1020. X            moveto (x_coord, y_coord, 1);        /*    do gen moveto        */
  1021. X
  1022. X        while (*c  && *c != '\n')
  1023. X        {
  1024. X            if (char_type == 0)
  1025. X                fputc ('(', output_fp);
  1026. X                
  1027. X            switch ((int) *c)
  1028. X            {
  1029. X            case ESCAPE:
  1030. X                previous_attribute = print_attribute;
  1031. X                esc_type = *(++c);
  1032. X                if (escape_sequence (esc_type) == 0)
  1033. X                {
  1034. X                    switch (esc_type)
  1035. X                    {
  1036. X                    case 'u':
  1037. X                        SHOWU (output_fp, point_size);
  1038. X                        break;
  1039. X                    
  1040. X
  1041. X                    default:
  1042. X                        if (char_type  &&  (previous_attribute & UNDERLINE))
  1043. X                            SHOWU (output_fp, point_size);
  1044. X/*
  1045. X                        else
  1046. X                            if (c == line + 1  && (esc_type == '+'  || esc_type == '-'))
  1047. X                                ;
  1048. X*/
  1049. X                        else
  1050. X                            fputs (")show\n", output_fp);
  1051. X
  1052. X                        if (esc_type == '+'  ||  esc_type == '-')
  1053. X
  1054. X                        /*    check for +/- 1/2 line feed        */
  1055. X                        
  1056. X                        {
  1057. X                            if (esc_type == '+')
  1058. X                                y_coord -= point_size / 2;
  1059. X                            else
  1060. X                                y_coord += point_size / 2;
  1061. X
  1062. X                            moveto (x_coord, y_coord, 1);
  1063. X                            char_type = -1;
  1064. X                            c++;
  1065. X                            if (*c != '\n')
  1066. X                                fputc ('(', output_fp);
  1067. X                            continue;
  1068. X                        }
  1069. X                        else
  1070. X                            findfont (output_fp);
  1071. X                    }
  1072. X                    char_type = 0;
  1073. X                }
  1074. X                break;
  1075. X                
  1076. X            default:
  1077. X                if (*c == '\t')
  1078. X                {
  1079. X                    fputc (' ', output_fp);
  1080. X                    while (++char_count % tab_size)
  1081. X                        fputc (' ', output_fp);
  1082. X                }
  1083. X                else
  1084. X                {    if (strchr ("\r\b\\()", *c) != NULL)
  1085. X                        fputc ('\\', output_fp);
  1086. X                    fputc (*c, output_fp);
  1087. X                    char_count++;
  1088. X                }
  1089. X                char_type = 1;
  1090. X                break;
  1091. X            }
  1092. X            c++;
  1093. X        }
  1094. X        if (char_type == 1)
  1095. X        {    if (print_attribute & UNDERLINE)
  1096. X                SHOWU (output_fp, point_size);
  1097. X            else
  1098. X                fputs (")show\n", output_fp);
  1099. X        }
  1100. X
  1101. X        y_coord -= point_size;
  1102. X        x_coord = 0;
  1103. X        if (set_page)
  1104. X        {    line_number = 32000;
  1105. X            set_page = 0;
  1106. X        }
  1107. X    }
  1108. X}
  1109. X
  1110. X/****************************************************************************
  1111. X*    escape_sequence ()                                                        *
  1112. X*    If an escape sequence (esc,char) is found, mark which type of font        *
  1113. X****************************************************************************/
  1114. X
  1115. Xint escape_sequence (which)
  1116. Xint    which;
  1117. X{    unsigned char    s[10];
  1118. X
  1119. X    switch (which)
  1120. X    {
  1121. X    case 'I':
  1122. X        print_attribute |= ITALICS;
  1123. X        break;
  1124. X
  1125. X    case 'i':
  1126. X        print_attribute &= ~ITALICS;
  1127. X        break;
  1128. X
  1129. X    case 'B':
  1130. X        print_attribute |= BOLD;
  1131. X        break;
  1132. X
  1133. X    case 'b':
  1134. X        print_attribute &= ~BOLD;
  1135. X        break;
  1136. X
  1137. X    case 'U':
  1138. X        print_attribute |= UNDERLINE;
  1139. X        break;
  1140. X
  1141. X    case 'u':
  1142. X        print_attribute &= ~UNDERLINE;
  1143. X        break;
  1144. X    
  1145. X    case 'F':
  1146. X        s[0] = *(++c);
  1147. X        s[1] = '\0';
  1148. X        font_number = atoi (s);        
  1149. X        if (font_number > (NFONTS / 4))
  1150. X            font_number = (NFONTS / 4) - 1;
  1151. X        break;
  1152. X    
  1153. X    case 'f':
  1154. X        font_number = default_font_number;
  1155. X        break;
  1156. X        
  1157. X    case 'P':
  1158. X        s[0] = *(++c);
  1159. X        s[1] = *(++c);
  1160. X        s[2] = '\0';
  1161. X        point_size = atoi (s);
  1162. X        break;
  1163. X
  1164. X    case 'p':
  1165. X        point_size = default_point_size;
  1166. X        break;
  1167. X
  1168. X    case '+':
  1169. X    case '-':
  1170. X        break;
  1171. X    
  1172. X    default:
  1173. X        return (-1);
  1174. X        ;
  1175. X    }
  1176. X    return (0);
  1177. X}
  1178. X
  1179. X/****************************************************************************
  1180. X*    moveto ()                                                                *
  1181. X*    Generate a postscript     x y moveto    statememt                        *
  1182. X****************************************************************************/
  1183. X
  1184. Xmoveto (x, y, do_move)
  1185. Xint    x;
  1186. Xint    y;
  1187. Xint do_move;            /*    1 = gen moveto     0 = dont gen moveto    */
  1188. X{
  1189. X    /*    ensure that the current line can fit on the page - including the
  1190. X        1/4 line needed for the decenders
  1191. X    */
  1192. X
  1193. X    if (line_number > lines_on_page * 10  ||  y < (p->bot_marg + point_size / 3))
  1194. X    {
  1195. X        showpage (0);
  1196. X        if (header)
  1197. X        {
  1198. X            put_top();
  1199. X            line_number += 20;
  1200. X        }
  1201. X        y = y_coord;
  1202. X        x = x_coord;
  1203. X    }
  1204. X
  1205. X    if (do_move)
  1206. X        fprintf (output_fp, "%d %d moveto\n", x + x_left_offset, y);
  1207. X}
  1208. X
  1209. X/****************************************************************************
  1210. X*    findfont ()                                                                *
  1211. X*    generate a findfont statement                                            *
  1212. X****************************************************************************/
  1213. X
  1214. Xfindfont ()
  1215. X{    int    this;
  1216. X
  1217. X    /*    remove reference to UNDERLINE.  Underline is not a font.    */
  1218. X    
  1219. X    this = (font_number * 4) + (print_attribute & 0x03);
  1220. X    fonts_used[this] = 1;
  1221. X    fprintf (output_fp, "/%s findfont %d scalefont setfont\n", fonts[this], point_size);
  1222. X}
  1223. X
  1224. X/****************************************************************************
  1225. X*    start_file ()                                                            *
  1226. X*    Generate things that are appropriate for beginning of file processing    *
  1227. X****************************************************************************/
  1228. X
  1229. Xstart_file ()
  1230. X{
  1231. X    line_number = 0;
  1232. X    print_attribute = 0;
  1233. X    page_number = 0;
  1234. X    frame = -1;
  1235. X    showpage (0);
  1236. X    if (header)
  1237. X    {
  1238. X        put_top();
  1239. X        line_number += 20;
  1240. X    }
  1241. X}
  1242. X
  1243. X/****************************************************************************
  1244. X*    terminate_file ()                                                        *
  1245. X*    Generate things that are appropriate for end of file processing            *
  1246. X****************************************************************************/
  1247. X
  1248. Xterminate_file ()
  1249. X{
  1250. X    showpage (1);
  1251. X}
  1252. X
  1253. X
  1254. X/****************************************************************************
  1255. X*    terminate_printer ()                                                    *
  1256. X*    Generate things that are appropriate wrap-up after all files printed    *
  1257. X*    For double sided printing (book == 1), generate byte offset info.        *
  1258. X****************************************************************************/
  1259. X
  1260. Xterminate_printer ()
  1261. X{    int    i, used;
  1262. X    long    psfptr;
  1263. X    
  1264. X    if (book)
  1265. X    {    pg_loc[npg_loc++] = ftell (output_fp);
  1266. X    }
  1267. X    fprintf (output_fp, "%%%%Trailer\n");
  1268. X    for (used = i = 0;  i < NFONTS;  i++)
  1269. X    {    if (fonts_used[i])
  1270. X        {    used = 1;
  1271. X            break;
  1272. X        }
  1273. X    }
  1274. X    if (used)
  1275. X    {    fprintf (output_fp, "%%%%DocumentFonts:");
  1276. X        for (i = 0;  i < NFONTS;  i ++)
  1277. X        {    if (fonts_used[i])
  1278. X                fprintf (output_fp, " %s", fonts[i]);
  1279. X        }
  1280. X        fprintf (output_fp, "\n");
  1281. X    }
  1282. X            
  1283. X    fprintf (output_fp, "%%%%Pages: %d\n", physical_page);
  1284. X
  1285. X    if (book)            /*    print statistics for psd  */
  1286. X    {
  1287. X        psfptr = ftell (output_fp);
  1288. X        fprintf (output_fp, "%%PsfScale: %.5f %.5f scale\n", scale_x, scale_y);
  1289. X        fprintf (output_fp, "%%PsfMargin: %d %d %d %d %d\n", 
  1290. X                        max_frame, landscape, real_width, p->height, p->width);
  1291. X        for (i = 0;  i < 4;  i++)
  1292. X            fprintf (output_fp, "%%PsfHome: %d %d %d\n",  i, dx_home[i], dy_home[i]);
  1293. X        for (i = 0;  i < npg_loc-1;  i++)
  1294. X            fprintf (output_fp, "%%PsfPg: %d %d\n",  i, pg_loc[i]);
  1295. X        fprintf (output_fp, "%%PsfPg: 9999 %d\n", pg_loc[npg_loc-1]);
  1296. X        fprintf (output_fp, "%%PsfPtr: %d\n", psfptr);
  1297. X    }
  1298. X    fprintf (output_fp, "%c", 0x04);        /* CTL/D = end job */
  1299. X}
  1300. X
  1301. X/****************************************************************************
  1302. X*    draw_cross ()                                                            *
  1303. X*    Draw horizontal and vertical separation lines between pages 4-up        *
  1304. X****************************************************************************/
  1305. X
  1306. Xdraw_cross ()
  1307. X{    int     p_w, p_h;
  1308. X    
  1309. X    if (max_frame == 4)
  1310. X    {    p_w = p->width;
  1311. X        p_h = p->height;
  1312. X        fprintf (output_fp,"%d %d moveto\n", p_w, p_h);
  1313. X        fprintf (output_fp,"%d %d lineto\n", p_w, -p_h);
  1314. X        fprintf (output_fp,"%d %d moveto\n", 0, 0);
  1315. X        fprintf (output_fp,"%d %d lineto\n", p_w * 2, 0);
  1316. X        fprintf (output_fp,"%s\n", "stroke");
  1317. X    }
  1318. X}
  1319. X
  1320. X/****************************************************************************
  1321. X*    output_book ()                                                            *
  1322. X*    Send file "double sided print" mode.  Used to make a "book".            *
  1323. X*    Will pause the printer to ask for stack re-feed                            *
  1324. X****************************************************************************/
  1325. X
  1326. Xoutput_book ()
  1327. X{
  1328. X#ifdef HOPPER
  1329. X    if (nslots > 1)
  1330. X    {
  1331. X        fflush (output_fp);
  1332. X        fclose (output_fp);
  1333. X        strcpy (line, BINDIR);
  1334. X        if (*line)
  1335. X            strcat (line, "/");
  1336. X        strcat (line, "psd -3 1psbook2.d34");
  1337. X        system (line);
  1338. X        unlink ("1psbook2.d34");
  1339. X    }
  1340. X#endif
  1341. X}
  1342. X
  1343. Xstatic char *usage_text[] =
  1344. X{    "Usage: psf [-1|2|4] [-b n] [-c n] [-d] [-f n] [-g type ] [-h] [-H text]",
  1345. X    "           [-i n]   [-l n] [-m n] [-n] [-p n] [-t n]     [-w] [-x] file...",
  1346. X    "where:",
  1347. X    "   -1|2|4  print 1,2,4 up (default=1)",
  1348. X    "   -b n    paper bin n",
  1349. X    "   -c n    print columns",
  1350. X    "   -d      double sided",
  1351. X    "   -f n    font number (def=0:Courier)",
  1352. X    "   -g type letter legal a4 b5",
  1353. X    "   -h      file name header",
  1354. X    "   -H text text header",
  1355. X    "   -i n    indent left margin points",
  1356. X    "   -l n    print lines per page",
  1357. X    "   -L n    lines per page",
  1358. X    "   -m n    top margin points",
  1359. X    "   -n      portrait (narrow) format",
  1360. X    "   -p n    point size n",
  1361. X    "   -t n    tabs to n (default=8)",
  1362. X    "   -w      landscape (wide) format",
  1363. X    "   -x      draw cross (4-up page)",
  1364. X    "   file..  name of files (or stdin)",
  1365. X    "   output: stdout",
  1366. X    ""
  1367. X} ;
  1368. X    
  1369. Xusage ()
  1370. X{    int        i, many, n, ff;
  1371. X
  1372. X    for (i = 0;  i < 3; i++)
  1373. X        fprintf (stderr, "%s\n", usage_text[i]);
  1374. X
  1375. X    many = sizeof (usage_text)/sizeof (char *) - 3;
  1376. X    
  1377. X    for (i = 0;  i < many/2;  i++)
  1378. X        fprintf (stderr, "%-38s %-38s\n", usage_text[i+3], usage_text[i+many/2+3]);
  1379. X
  1380. X    fprintf (stderr,"Fonts selection with -f n (number or name)\n");
  1381. X    many = 0;
  1382. X    for (i = 0;  i < NFONTS/4;  i++)
  1383. X    {    if (fonts_have[i*4])
  1384. X        {    fprintf (stderr, "%2d %-18s", i, fonts[i*4]);
  1385. X            many++;
  1386. X            if ((ff = many % 3)  == 0)
  1387. X                fprintf (stderr, "\n");
  1388. X        }
  1389. X    }
  1390. X    if (ff)
  1391. X        fprintf (stderr, "\n");
  1392. X
  1393. X    fprintf (stderr, "Paper type/size selection with -g type\n");
  1394. X    many = 0;
  1395. X    for (i = 0;  page_types[i].paper_name[0] != '\0';  i++)
  1396. X    {    n = strlen (page_types[i].paper_name);
  1397. X        if (many + n > 75)
  1398. X        {    many = 0;
  1399. X            fprintf (stderr,"\n");
  1400. X            ff = 0;
  1401. X        }
  1402. X        else ff = 1;
  1403. X        many += n + 3;
  1404. X        fprintf (stderr,"   %s", page_types[i].paper_name);
  1405. X    }    
  1406. X    if (ff)
  1407. X        fprintf (stderr, "\n");
  1408. X    exit (0);
  1409. X}
  1410. X
  1411. X/************************************************
  1412. X*        tscan (s,t)                                *
  1413. X*        char    s[],t[];                        *
  1414. X*                                                *
  1415. X*    Index function as defined in K&R            *
  1416. X*    Look for string t in s                        *
  1417. X*                                                *
  1418. X*    return -1 if t does not exits in s            *
  1419. X*    else return array position of first            *
  1420. X*    character match                                *
  1421. X************************************************/
  1422. X
  1423. X
  1424. Xtscan (s, t)
  1425. Xchar     s[], t[];
  1426. X{
  1427. X    int    i, j, k;
  1428. X    for (i = 0;  s[i] != '\0';  i++)
  1429. X    {    for (j = i, k=0;  t[k] != '\0'  &&  s[j] == t[k];  j++, k++)
  1430. X            ;
  1431. X        if (t[k] == '\0')
  1432. X            return (i);
  1433. X    }
  1434. X    return (-1);
  1435. X}
  1436. X
  1437. Xget_time (t)
  1438. Xchar    *t;
  1439. X{
  1440. X    long    n_time, time ();
  1441. X    char    *x_time, *cc, *strchr();
  1442. X    
  1443. X    n_time = time (0);            /* get time */
  1444. X    x_time = ctime (&n_time);    /* convert ascii */
  1445. X    if ((cc = strchr (x_time, '\n')) != NULL)
  1446. X        *cc = '\0';
  1447. X    strcpy (t, x_time);
  1448. X}
  1449. X
  1450. Xcompare (a,b)
  1451. Xchar    *a, *b;
  1452. X{    int    aa, bb;
  1453. X
  1454. X    while (*a  &&  *b)
  1455. X    {    aa = *a++;
  1456. X        bb = *b++;
  1457. X        if (toupper (aa)  !=  toupper (bb))
  1458. X            return (aa - bb);
  1459. X    }
  1460. X    return (0);
  1461. X}
  1462. X
  1463. Xcomp (a,b)
  1464. Xchar    *a, *b;
  1465. X{    int    aa, bb;
  1466. X
  1467. X    while (*a  &&  *b)
  1468. X    {    aa = *a++;
  1469. X        bb = *b++;
  1470. X        if (toupper (aa)  !=  toupper (bb))
  1471. X            return (aa - bb);
  1472. X    }
  1473. X    if (*a == '\0'   &&  *b == '\n')
  1474. X        return (0);
  1475. X    return (*a - *b);
  1476. X}
  1477. X
  1478. Xtrim (s)
  1479. Xchar    *s;
  1480. X{
  1481. X    while (*s)
  1482. X    {    if (*s < ' ')
  1483. X        {    *s = 0;
  1484. X            break;
  1485. X        }
  1486. X        s++;
  1487. X    }
  1488. X}
  1489. X
  1490. Xbad_file()
  1491. X{
  1492. X    fprintf (stderr, "Bad %s file\n", PDEF);
  1493. X    exit (1);
  1494. X}
  1495. END_OF_FILE
  1496. if test 39736 -ne `wc -c <'psf.c'`; then
  1497.     echo shar: \"'psf.c'\" unpacked with wrong size!
  1498. fi
  1499. # end of 'psf.c'
  1500. fi
  1501. echo shar: End of archive 6 \(of 6\).
  1502. cp /dev/null ark6isdone
  1503. MISSING=""
  1504. for I in 1 2 3 4 5 6 ; do
  1505.     if test ! -f ark${I}isdone ; then
  1506.     MISSING="${MISSING} ${I}"
  1507.     fi
  1508. done
  1509. if test "${MISSING}" = "" ; then
  1510.     echo You have unpacked all 6 archives.
  1511.     rm -f ark[1-9]isdone
  1512. else
  1513.     echo You still need to unpack the following archives:
  1514.     echo "        " ${MISSING}
  1515. fi
  1516. ##  End of shell archive.
  1517. exit 0
  1518.  
  1519.